package com.sencorsta.ids.game.world.pak;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sencorsta.ids.common.information.ErrorCodeList;
import com.sencorsta.ids.common.proto.utils.ReturnUtils;
import com.sencorsta.ids.common.service.MsgService;
import com.sencorsta.ids.common.service.MysqlService;
import com.sencorsta.ids.common.service.RedisService;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.game.db.RpMassage;
import com.sencorsta.ids.game.db.SettlementResult;
import com.sencorsta.ids.game.db.Wallet;
import com.sencorsta.ids.game.proto.GamePushRedPackageByProto;
import com.sencorsta.ids.game.proto.GamePushRobMoneyByProto;
import com.sencorsta.ids.game.util.PacketMoney;
import com.sencorsta.ids.game.util.PushAndSaved;
import com.sencorsta.ids.game.world.bean.Player;
import com.sencorsta.ids.game.world.bean.World;
import com.sencorsta.ids.game.world.room.NiuniuRoom;
import com.sencorsta.utils.date.DateUtil;

import java.util.*;

/**
 * @author TAO
 * @description: 牛牛玩法
 * @date 2019/11/14 19:40
 */
public class NiuNiuPackage extends RedPackage implements RedisService {

    public int bankerNiuNumber;//庄家点数

    public int victoryNumber = 0;//胜率


    public NiuniuRoom niuniuRoom;


    public NiuNiuPackage(String sendUserId, String rpId, int count, long amount, NiuniuRoom roomNiuniu, long sendDeposit, boolean isRobotPack) {
        super(sendUserId, rpId, count, amount, computeRobDeposit(amount, roomNiuniu), roomNiuniu.roomId, isRobotPack);//初始化父类公共属性
        this.moneyPieces = PacketMoney.getPacketMoney(PacketMoney.getRandomWeightsList(amount, count), amount, count, 2);
        this.sendDeposit = sendDeposit;//为发包者初始化冻结资金\
        this.niuniuRoom = roomNiuniu;
        analysis();
    }

    //得到抢红包的人的押金multiplyingPower
    public static long computeRobDeposit(long amount, NiuniuRoom roomNiuniu) {
        double maxMagnification = roomNiuniu.getMaxMagnification();//最高倍率
        return (long) (amount * maxMagnification);//为押金赋值
    }

    //抢红包
    public void rob(Player player) {
        if (player.userId.equals(sendUserId) && !isRobedBySend) {
            isRobedBySend = true;
            JSONObject rpResule = rpResult;//得到当前红包记录
            JSONObject jsonObject = rpResule.getJSONObject(sendUserId);
            GamePushRobMoneyByProto.PushRobMoney.Builder push = GamePushRobMoneyByProto.PushRobMoney.newBuilder();
            push.setGameId(World.NIUNIU);
            push.setRoomId(roomId);
            push.setRpId(rpId);
            push.setMoney(jsonObject.getLong("amount"));
            Out.debug("牛牛即将为==》", player.userId, "__推送__");
            MsgService.pushBySID(PushAndSaved.pushProto(player.userId, "push.RobMoney", push), player.SID);
            return;
        }


        Out.debug("-----------牛牛抢红包--update-----------");
        if (count == 1 && !rpResult.containsKey(sendUserId) && !player.userId.equals(sendUserId)) {
            Out.debug("发包者还没有抢包");
            return;
        }

        if (count == 0 || status != 0) {//判断红包数量
            Out.debug("红包已抢完");
            return;
        }

        if (rpResult.containsKey(player.userId)) {
            Out.debug("该红包你以领取过");
            return;
        }

        Long robAmount;//抢到的红包金额
        int niuNiuNumber;//牛数

        //不加控制默认
        int index = getNextIndex();
        if (!isRobotPack && player.type == 2 && isRobotRobMustWin) {
            if (isRobotRobMustWin) {
                index = getWinIndex();
                if (index < 0) {
                    //没有可以用的包了
                    return;
                }
            }
        }

        robAmount = moneyPieces.get(index).getMoney();//直接将剩余红包金额给最后一个人
        niuNiuNumber = moneyPieces.get(index).getNiuNumber();

        playerMap.put(player.userId, player);
        moneyPieces.get(index).setRobed(true);


//        JSONObject rpResule = rpResult;//得到当前红包记录
        //将抢的红包和用户对应起来
        JSONObject result = new JSONObject();
        result.put("robUserId", player.userId);
        result.put("amount", robAmount);
        result.put("niuNumber", niuNiuNumber);
        result.put("time", DateUtil.getDateTime());
        result.put("nickname", player.nickname);
        result.put("portrait", player.portrait);
        rpResult.put(player.userId, result);

        balance = balance - robAmount;

        player.onRob(rpId, -robDeposit, robDeposit);

        GamePushRobMoneyByProto.PushRobMoney.Builder push = GamePushRobMoneyByProto.PushRobMoney.newBuilder();
        push.setGameId(World.NIUNIU);
        push.setRoomId(roomId);
        push.setRpId(rpId);
        push.setMoney(robAmount);
        Out.debug("牛牛即将为==》", player.userId, "__推送__");
        //MsgService.pushOnlyOnline(PushAndSaved.pushProto(player.userId, "push.RobMoney", push));
        MsgService.pushBySID(PushAndSaved.pushProto(player.userId, "push.RobMoney", push), player.SID);

        if (!moneyRecode.containsKey(player.userId)) {//参与抢包用户添加recode的--防止报空
            JSONObject recode = new JSONObject();
            moneyRecode.put(player.userId, recode);
        }
        count = count - 1;

    }

    public void rob2(Player player) {
        Out.debug("-----------牛牛抢红包222--update-----------");

        Long robAmount;//抢到的红包金额
        int niuNiuNumber;//牛数

        //不加控制默认
        int index = getSendIndex();

        robAmount = moneyPieces.get(index).getMoney();
        niuNiuNumber = moneyPieces.get(index).getNiuNumber();

        moneyPieces.get(index).setRobed(true);


        //将抢的红包和用户对应起来
        JSONObject result = new JSONObject();
        result.put("robUserId", player.userId);
        result.put("amount", robAmount);
        result.put("niuNumber", niuNiuNumber);
        result.put("time", DateUtil.getDateTime());
        result.put("nickname", player.nickname);
        result.put("portrait", player.portrait);
        rpResult.put(player.userId, result);

        balance = balance - robAmount;
        playerMap.put(player.userId, player);

        //冻结抢包者的最高赔款金额 --防止在抢到红包到结算期间去抢其他红包（最终导致这里的包在结算时余额不够）
        player.onRob(rpId, -robDeposit, robDeposit);

        if (!moneyRecode.containsKey(player.userId)) {//参与抢包用户添加recode的--防止报空
            JSONObject recode = new JSONObject();
            moneyRecode.put(player.userId, recode);
        }
        count = count - 1;
    }

    public void update() {
        //得到当前红包的数量
        this.time -= 1;//当前包的时间减1秒
        Out.debug("当前牛牛红包Id==>", rpId, "__房间为==>", niuniuRoom.roomId, "  count==>", count, "  time==>", time);

        if (status == 0) {
            if (time == 0) {//当前包的死期已到，他妈的干掉
                if (rpResult == null) {//红包结算记录为空，代表
                    Out.debug("当前包无人问津，自动撤回");
                    status = 2;
                    Settlement();//结算
                    return;
                }
                Out.debug("当前包的死期已到，开始清算结果");
                status = 1;
                Settlement();//结算
                return;
            }

            if (count == 0) {//红包抢完了
                Out.debug("当前红包已抢完", "红包Id", rpId);
                status = 1;
                Settlement();//结算
                return;
            }
        }

    }

    @Override
    public void analysis() {
        //判断是否是机器人发包
        int i;
        boolean isMustWin = World.getInstance().isMustWinbyRoom(roomId);
        if (isRobotPack) {//机器人发包
            //机器人发包时 机器人拿最好的包 机器人随便抢
            isRobotRobMustWin = false;
            if (isMustWin) {
                i = getMaxScore();
            } else {
                i = getNextIndex();
            }
        } else {//玩家发包
            if (isMustWin) {
                //玩家发包时 如果必赢 机器人只抢赢钱的包
                isRobotRobMustWin = true;
                i = getMinScore();
            } else {
                i = getNextIndex();
            }
        }
        moneyPieces.get(i).setSend(true);

        for (int j = 0; j < moneyPieces.size(); j++) {
            //和庄家比判断这个包是否输
            if (j == i) {
                continue;
            }
            if (moneyPieces.get(j).getNiuNumber() > moneyPieces.get(i).getNiuNumber()) {
                moneyPieces.get(j).setWin(true);
            } else {
                moneyPieces.get(j).setWin(false);
            }
        }
    }

    //通知结算
    public void Settlement() {
        try {


            NiuniuRoom niuniuRoom = (NiuniuRoom) World.getInstance().games.get(World.NIUNIU).rooms.get(roomId);//得到当前房间

            Out.debug("------------------------通知结算牛牛包----rpResult----------------------------");
            Out.debug("牛牛红包详情：", this.toString());
            Out.debug("牛牛红包记录：", rpResult);
            String bankerUserId = sendUserId;//得到庄家

            JSONObject jsz = (JSONObject) rpResult.get(sendUserId);

            int bankerNiuNumber = jsz.getInteger("niuNumber");//得到庄家的牛数
            if (bankerNiuNumber == 0) {
                bankerNiuNumber = 10;
            }
            this.bankerNiuNumber = bankerNiuNumber;//给庄家赋牛数
            Map<Integer, Double> magnification = niuniuRoom.magnification;//得到当前房间的个牛的倍率


            long bankWinMoney = 0;
            for (var userId : rpResult.keySet()) {

                JSONObject userRobInfo = (JSONObject) rpResult.get(userId);//得到的userId的结算记录
                int leisureNiuNumber = userRobInfo.getInteger("niuNumber");//得到当前用户的牛数
                long leisureAmount = userRobInfo.getLong("amount");//得到当前用户抢到的钱

                Out.debug("leisureNiuNumber-->", leisureNiuNumber);
                Out.debug("magnification.keySet().size()==>", magnification.keySet().size());

                double currentMagnification = 1;//当前牛倍率

                if (leisureNiuNumber == 0) {
                    leisureNiuNumber = 10;
                }

                JSONObject recod = moneyRecode.getJSONObject(userId);//得到当前玩家的账单记录
                recod.put("robMoney", leisureAmount);//将抢到的钱存到当前玩家的账单记录
                if (!userId.equals(bankerUserId)) {//结算记录排除发包者

                    JSONObject recode = moneyRecode.getJSONObject(userId);
                    if (bankerNiuNumber >= leisureNiuNumber) {//庄赢
                        victoryNumber = ++victoryNumber;//胜利数++
                        if (magnification.keySet().size() > 0) {//倍率存在
                            currentMagnification = magnification.get(bankerNiuNumber);//得到庄家倍率
                        }
                        long transportAmount = getTransportAmount(amount, currentMagnification);
                        recode.put("resultMoney", -transportAmount);//扣钱
                        bankWinMoney += transportAmount;
                    } else {
                        if (magnification.keySet().size() > 0) {//倍率存在
                            currentMagnification = magnification.get(leisureNiuNumber);
                        }
                        long transportAmount = getTransportAmount(amount, currentMagnification);
                        recode.put("resultMoney", transportAmount);//扣钱
                        bankWinMoney -= transportAmount;
                    }
                }
            }
            moneyRecode.getJSONObject(sendUserId).put("sendAmountback", balance);//发包者剩余的钱
            moneyRecode.getJSONObject(sendUserId).put("resultMoney", bankWinMoney);
            JSONArray array = new JSONArray();
            for (String userId : moneyRecode.keySet()) {
                JSONObject resultItem = moneyRecode.getJSONObject(userId);
                long total = 0;
                total += resultItem.getLongValue("sendAmount") + resultItem.getLongValue("sendAmountback") + resultItem.getLongValue("robMoney") + resultItem.getLongValue("resultMoney");
                long drawWater = getWinAmount(total, playerMap.get(userId));//手续费
                if (moneyRecode.keySet().size() == 1 && userId.equals(sendUserId)) {
                    //只有发包者自己的话不算手续费
                    drawWater = 0;
                }
                resultItem.put("drawWater", drawWater);

                long totalFreeze = 0;
                long finalMoney = total - drawWater;

                if (userId.equals(sendUserId)) {
                    totalFreeze = sendDeposit + robDeposit;
                } else {
                    totalFreeze = robDeposit;
                }
                resultItem.put("total", finalMoney);

                playerMap.get(userId).onSettlement(rpId, finalMoney + totalFreeze, -totalFreeze);
                array.add(Wallet.addMoneySql(playerMap.get(userId), finalMoney, 0, roomId));
                array.add(SettlementResult.makeResult(this, resultItem, userId, World.NIUNIU));//插入流水账单
            }
            array.add(RpMassage.insertRpMessage(rpId, roomId, World.NIUNIU, 2));
            MysqlService.getInstance().executeMultipleAsyn(array);

            //Redis 红包详情入库
            niuNiuJoinRedis();

            GamePushRedPackageByProto.PushRedPackage.Builder push = GamePushRedPackageByProto.PushRedPackage.newBuilder();
            push.setGameId(World.NIUNIU);
            push.setRoomId(roomId);
            push.setRpId(rpId);


            Out.debug("牛牛红包详情：", this.toString());
            Out.debug("牛牛红包记录：", rpResult);
            niuniuRoom.rpPackage.remove(rpId);//内存中移除红包

            World.getInstance().games.get(World.NIUNIU).rooms.get(roomId).broadcast(PushAndSaved.pushProto("", "push.RedPackage", push), "proxy");
            for (Player current : playerMap.values()) {
                MsgService.pushBySID(PushAndSaved.pushProto(current.userId, "push.RedPackageResult", push), current.SID);
            }
        } catch (Exception e) {
            Out.error("牛牛结算报错");
            Out.error(this.toString());
            e.printStackTrace();
        }
    }

    //Redis 红包详情入库
    public void niuNiuJoinRedis() {
        //将红包记录插到MySql库里
        RpMassage.insertRpMessage(rpId, roomId, World.NIUNIU, 2);
        Map<String, String> rpInfo = new HashMap<>();
        rpInfo.put("sendUserId", sendUserId);//发红包者
        rpInfo.put("gameId", String.valueOf(World.NIUNIU));//房间Id
        rpInfo.put("roomId", String.valueOf(roomId));//房间Id
        rpInfo.put("RpId", rpId);//红包Id
        rpInfo.put("count", String.valueOf(count));//红包余数
        rpInfo.put("sumCount", String.valueOf(sumCount));//红包总个数
        rpInfo.put("amount", String.valueOf(amount));//红包金额
        rpInfo.put("balance", String.valueOf(balance));//红包余额
        rpInfo.put("moneyPieces", JSON.toJSONString(moneyPieces));//金额分配
        rpInfo.put("rpResult", String.valueOf(rpResult));//红包结果
        rpInfo.put("time", String.valueOf(time));//红包时间
        rpInfo.put("status", String.valueOf(status));//红包状态  0:发出 1:完成  2.撤回
        rpInfo.put("robDeposit", String.valueOf(robDeposit));//押金
        rpInfo.put("victoryNumber", String.valueOf(victoryNumber));//胜率
        rpInfo.put("bankerNiuNumber", String.valueOf(bankerNiuNumber));//庄家牛数
        R_REDPACKAGE_INFO.hmset(rpId, rpInfo);
    }


    //得到输的金额
    public static long getTransportAmount(long amount, double currentMagnification) {
        //输的金额 = 总金额 * 牛数倍率
        return (long) (amount * currentMagnification);
    }


}
